Skip to content

fix(init): generate root CLAUDE.md for --ai claude#1988

Open
arun-gupta wants to merge 8 commits intogithub:mainfrom
arun-gupta:fix-claude-md-init-1983
Open

fix(init): generate root CLAUDE.md for --ai claude#1988
arun-gupta wants to merge 8 commits intogithub:mainfrom
arun-gupta:fix-claude-md-init-1983

Conversation

@arun-gupta
Copy link
Copy Markdown

Ensure specify init --ai claude creates a minimal root CLAUDE.md pointing to .specify/memory/constitution.md

Made-with: Cursor

Description

Fixes #1983

Testing

Ran the tests on my machine.

  • [] Tested locally with uv run specify --help
  • Ran existing tests with uv sync && uv run pytest

Here is the output:

(specify-cli) arungupta@Mac spec-kit % python -m pytest tests/test_ai_skills.py
========================================================== test session starts ==========================================================
platform darwin -- Python 3.13.5, pytest-9.0.2, pluggy-1.6.0 -- /Users/arungupta/workspaces/spec-kit/.venv/bin/python3
cachedir: .pytest_cache
rootdir: /Users/arungupta/workspaces/spec-kit
configfile: pyproject.toml
plugins: cov-7.1.0, anyio-4.13.0
collected 98 items                                                                                                                      

tests/test_ai_skills.py::TestGetSkillsDir::test_claude_skills_dir PASSED                                                          [  1%]
tests/test_ai_skills.py::TestGetSkillsDir::test_gemini_skills_dir PASSED                                                          [  2%]
tests/test_ai_skills.py::TestGetSkillsDir::test_tabnine_skills_dir PASSED                                                         [  3%]
tests/test_ai_skills.py::TestGetSkillsDir::test_copilot_skills_dir PASSED                                                         [  4%]
tests/test_ai_skills.py::TestGetSkillsDir::test_codex_skills_dir_from_agent_config PASSED                                         [  5%]
tests/test_ai_skills.py::TestGetSkillsDir::test_cursor_agent_skills_dir PASSED                                                    [  6%]
tests/test_ai_skills.py::TestGetSkillsDir::test_kiro_cli_skills_dir PASSED                                                        [  7%]
tests/test_ai_skills.py::TestGetSkillsDir::test_pi_skills_dir PASSED                                                              [  8%]
tests/test_ai_skills.py::TestGetSkillsDir::test_unknown_agent_uses_default PASSED                                                 [  9%]
tests/test_ai_skills.py::TestGetSkillsDir::test_all_configured_agents_resolve PASSED                                              [ 10%]
tests/test_ai_skills.py::TestKimiLegacySkillMigration::test_migrates_legacy_dotted_skill_directory PASSED                         [ 11%]
tests/test_ai_skills.py::TestKimiLegacySkillMigration::test_removes_legacy_dir_when_hyphenated_target_exists_with_same_content PASSED [ 12%]
tests/test_ai_skills.py::TestKimiLegacySkillMigration::test_keeps_legacy_dir_when_hyphenated_target_differs PASSED                [ 13%]
tests/test_ai_skills.py::TestKimiLegacySkillMigration::test_keeps_legacy_dir_when_matching_target_but_extra_files_exist PASSED    [ 14%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_installed_with_correct_structure PASSED                                 [ 15%]
tests/test_ai_skills.py::TestInstallAiSkills::test_generated_skill_has_parseable_yaml PASSED                                      [ 16%]
tests/test_ai_skills.py::TestInstallAiSkills::test_empty_yaml_frontmatter PASSED                                                  [ 17%]
tests/test_ai_skills.py::TestInstallAiSkills::test_enhanced_descriptions_used_when_available PASSED                               [ 18%]
tests/test_ai_skills.py::TestInstallAiSkills::test_template_without_frontmatter PASSED                                            [ 19%]
tests/test_ai_skills.py::TestInstallAiSkills::test_missing_templates_directory PASSED                                             [ 20%]
tests/test_ai_skills.py::TestInstallAiSkills::test_empty_templates_directory PASSED                                               [ 21%]
tests/test_ai_skills.py::TestInstallAiSkills::test_malformed_yaml_frontmatter PASSED                                              [ 22%]
tests/test_ai_skills.py::TestInstallAiSkills::test_additive_does_not_overwrite_other_files PASSED                                 [ 23%]
tests/test_ai_skills.py::TestInstallAiSkills::test_return_value PASSED                                                            [ 24%]
tests/test_ai_skills.py::TestInstallAiSkills::test_return_false_when_no_templates PASSED                                          [ 25%]
tests/test_ai_skills.py::TestInstallAiSkills::test_non_md_commands_dir_falls_back PASSED                                          [ 26%]
tests/test_ai_skills.py::TestInstallAiSkills::test_qwen_md_commands_dir_installs_skills PASSED                                    [ 27%]
tests/test_ai_skills.py::TestInstallAiSkills::test_pi_prompt_dir_installs_skills PASSED                                           [ 28%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[copilot] PASSED                                  [ 29%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[claude] PASSED                                   [ 30%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[gemini] PASSED                                   [ 31%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[cursor-agent] PASSED                             [ 32%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[qwen] PASSED                                     [ 33%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[opencode] PASSED                                 [ 34%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[codex] PASSED                                    [ 35%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[windsurf] PASSED                                 [ 36%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[junie] PASSED                                    [ 37%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[kilocode] PASSED                                 [ 38%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[auggie] PASSED                                   [ 39%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[codebuddy] PASSED                                [ 40%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[qodercli] PASSED                                 [ 41%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[roo] PASSED                                      [ 42%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[kiro-cli] PASSED                                 [ 43%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[amp] PASSED                                      [ 44%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[shai] PASSED                                     [ 45%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[tabnine] PASSED                                  [ 46%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[agy] PASSED                                      [ 47%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[bob] PASSED                                      [ 48%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[vibe] PASSED                                     [ 50%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[kimi] PASSED                                     [ 51%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[trae] PASSED                                     [ 52%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[pi] PASSED                                       [ 53%]
tests/test_ai_skills.py::TestInstallAiSkills::test_skills_install_for_all_agents[iflow] PASSED                                    [ 54%]
tests/test_ai_skills.py::TestInstallAiSkills::test_copilot_ignores_non_speckit_agents PASSED                                      [ 55%]
tests/test_ai_skills.py::TestInstallAiSkills::test_non_speckit_commands_ignored_for_all_agents[claude-review.md] PASSED           [ 56%]
tests/test_ai_skills.py::TestInstallAiSkills::test_non_speckit_commands_ignored_for_all_agents[cursor-agent-deploy.md] PASSED     [ 57%]
tests/test_ai_skills.py::TestInstallAiSkills::test_non_speckit_commands_ignored_for_all_agents[qwen-my-workflow.md] PASSED        [ 58%]
tests/test_ai_skills.py::TestInstallAiSkills::test_copilot_fallback_when_only_non_speckit_agents PASSED                           [ 59%]
tests/test_ai_skills.py::TestInstallAiSkills::test_fallback_when_only_non_speckit_commands[claude] PASSED                         [ 60%]
tests/test_ai_skills.py::TestInstallAiSkills::test_fallback_when_only_non_speckit_commands[cursor-agent] PASSED                   [ 61%]
tests/test_ai_skills.py::TestInstallAiSkills::test_fallback_when_only_non_speckit_commands[qwen] PASSED                           [ 62%]
tests/test_ai_skills.py::TestCommandCoexistence::test_existing_commands_preserved_claude PASSED                                   [ 63%]
tests/test_ai_skills.py::TestCommandCoexistence::test_existing_commands_preserved_gemini PASSED                                   [ 64%]
tests/test_ai_skills.py::TestCommandCoexistence::test_existing_commands_preserved_qwen PASSED                                     [ 65%]
tests/test_ai_skills.py::TestCommandCoexistence::test_commands_dir_not_removed PASSED                                             [ 66%]
tests/test_ai_skills.py::TestCommandCoexistence::test_no_commands_dir_no_error PASSED                                             [ 67%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_init_claude_creates_root_CLAUDE_md PASSED                                [ 68%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_new_project_commands_removed_after_skills_succeed PASSED                 [ 69%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_new_project_nonstandard_commands_subdir_removed_after_skills_succeed PASSED [ 70%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_codex_native_skills_preserved_without_conversion PASSED                  [ 71%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_codex_native_skills_missing_falls_back_then_fails_cleanly PASSED         [ 72%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_codex_native_skills_ignores_non_speckit_skill_dirs PASSED                [ 73%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_kimi_legacy_migration_runs_without_ai_skills_flag PASSED                 [ 74%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_codex_ai_skills_here_mode_preserves_existing_codex_dir PASSED            [ 75%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_codex_ai_skills_fresh_dir_does_not_create_codex_dir PASSED               [ 76%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_download_and_extract_template_blocks_zip_path_traversal[False] PASSED    [ 77%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_download_and_extract_template_blocks_zip_path_traversal[True] PASSED     [ 78%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_commands_preserved_when_skills_fail PASSED                               [ 79%]
tests/test_ai_skills.py::TestNewProjectCommandSkip::test_here_mode_commands_preserved PASSED                                      [ 80%]
tests/test_ai_skills.py::TestSkipIfExists::test_existing_skill_not_overwritten PASSED                                             [ 81%]
tests/test_ai_skills.py::TestSkipIfExists::test_fresh_install_writes_all_skills PASSED                                            [ 82%]
tests/test_ai_skills.py::TestSkipIfExists::test_existing_skill_overwritten_when_enabled PASSED                                    [ 83%]
tests/test_ai_skills.py::TestSkillDescriptions::test_all_known_commands_have_descriptions PASSED                                  [ 84%]
tests/test_ai_skills.py::TestCliValidation::test_ai_skills_without_ai_fails PASSED                                                [ 85%]
tests/test_ai_skills.py::TestCliValidation::test_ai_skills_without_ai_shows_usage PASSED                                          [ 86%]
tests/test_ai_skills.py::TestCliValidation::test_agy_without_ai_skills_fails PASSED                                               [ 87%]
tests/test_ai_skills.py::TestCliValidation::test_codex_without_ai_skills_fails PASSED                                             [ 88%]
tests/test_ai_skills.py::TestCliValidation::test_interactive_agy_without_ai_skills_prompts_skills PASSED                          [ 89%]
tests/test_ai_skills.py::TestCliValidation::test_interactive_codex_without_ai_skills_enables_skills PASSED                        [ 90%]
tests/test_ai_skills.py::TestCliValidation::test_kimi_next_steps_show_skill_invocation PASSED                                     [ 91%]
tests/test_ai_skills.py::TestCliValidation::test_ai_skills_flag_appears_in_help PASSED                                            [ 92%]
tests/test_ai_skills.py::TestCliValidation::test_kiro_alias_normalized_to_kiro_cli PASSED                                         [ 93%]
tests/test_ai_skills.py::TestCliValidation::test_q_removed_from_agent_config PASSED                                               [ 94%]
tests/test_ai_skills.py::TestParameterOrderingIssue::test_ai_flag_consuming_here_flag PASSED                                      [ 95%]
tests/test_ai_skills.py::TestParameterOrderingIssue::test_ai_flag_consuming_ai_skills_flag PASSED                                 [ 96%]
tests/test_ai_skills.py::TestParameterOrderingIssue::test_error_message_provides_hint PASSED                                      [ 97%]
tests/test_ai_skills.py::TestParameterOrderingIssue::test_error_message_lists_available_agents PASSED                             [ 98%]
tests/test_ai_skills.py::TestParameterOrderingIssue::test_ai_commands_dir_consuming_flag PASSED                                   [100%]

========================================================== 98 passed in 0.64s ===========================================================
  • Tested with a sample project (if applicable)

Here is the output

(specify-cli) arungupta@Mac spec-kit % specify init /tmp/speckit-test2 --ai claude
                                          ███████╗██████╗ ███████╗ ██████╗██╗███████╗██╗   ██╗                                           
                                          ██╔════╝██╔══██╗██╔════╝██╔════╝██║██╔════╝╚██╗ ██╔╝                                           
                                          ███████╗██████╔╝█████╗  ██║     ██║█████╗   ╚████╔╝                                            
                                          ╚════██║██╔═══╝ ██╔══╝  ██║     ██║██╔══╝    ╚██╔╝                                             
                                          ███████║██║     ███████╗╚██████╗██║██║        ██║                                              
                                          ╚══════╝╚═╝     ╚══════╝ ╚═════╝╚═╝╚═╝        ╚═╝                                              
                                                                                                                                         
                                            GitHub Spec Kit - Spec-Driven Development Toolkit                                            

╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│                                                                                                                                       │
│  Specify Project Setup                                                                                                                │
│                                                                                                                                       │
│  Project         speckit-test2                                                                                                        │
│  Working Path    /Users/arungupta/workspaces/spec-kit                                                                                 │
│  Target Path     /private/tmp/speckit-test2                                                                                           │
│                                                                                                                                       │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

Selected AI assistant: claude
Selected script type: sh
Initialize Specify Project
├── ● Check required tools (ok)
├── ● Select AI assistant (claude)
├── ● Select script type (sh)
├── ● Fetch latest release (release v0.4.3 (64,591 bytes))
├── ● Download template (spec-kit-template-claude-sh-v0.4.3.zip)
├── ● Extract template
├── ● Archive contents (26 entries)
├── ● Extraction summary (2 top-level items)
├── ● Ensure scripts executable (5 updated)
├── ● Constitution setup (copied from template)
├── ● Claude Code role file (created)
├── ● Cleanup
├── ● Initialize git repository (initialized)
└── ● Finalize (project ready)

Project ready.

╭──────────────────────────────────────────────────────── Agent Folder Security ────────────────────────────────────────────────────────╮
│                                                                                                                                       │
│  Some agents may store credentials, auth tokens, or other identifying and private artifacts in the agent folder within your project.  │
│  Consider adding .claude/ (or parts of it) to .gitignore to prevent accidental credential leakage.                                    │
│                                                                                                                                       │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

╭───────────────────────────────────────────────────────────── Next Steps ──────────────────────────────────────────────────────────────╮
│                                                                                                                                       │
│  1. Go to the project folder: cd /tmp/speckit-test2                                                                                   │
│  2. Start using slash commands with your AI agent:                                                                                    │
│     2.1 /speckit.constitution - Establish project principles                                                                          │
│     2.2 /speckit.specify - Create baseline specification                                                                              │
│     2.3 /speckit.plan - Create implementation plan                                                                                    │
│     2.4 /speckit.tasks - Generate actionable tasks                                                                                    │
│     2.5 /speckit.implement - Execute implementation                                                                                   │
│                                                                                                                                       │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

╭──────────────────────────────────────────────────────── Enhancement Commands ─────────────────────────────────────────────────────────╮
│                                                                                                                                       │
│  Optional commands that you can use for your specs (improve quality & confidence)                                                     │
│                                                                                                                                       │
│  ○ /speckit.clarify (optional) - Ask structured questions to de-risk ambiguous areas before planning (run before /speckit.plan if     │
│  used)                                                                                                                                │
│  ○ /speckit.analyze (optional) - Cross-artifact consistency & alignment report (after /speckit.tasks, before /speckit.implement)      │
│  ○ /speckit.checklist (optional) - Generate quality checklists to validate requirements completeness, clarity, and consistency        │
│  (after /speckit.plan)                                                                                                                │
│                                                                                                                                       │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
(specify-cli) arungupta@Mac spec-kit %

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (describe below)

I used Cursor to understand the codebase and generate the code for this particular fix. I read through the code 3x to ensure it's aligned with the rest of the codebase. I own the responsibility for this fix.

Ensure `specify init --ai claude` creates a minimal root CLAUDE.md pointing to `.specify/memory/constitution.md`, and add a regression test for issue github#1983.

Made-with: Cursor
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Ensures specify init --ai claude creates a minimal root CLAUDE.md so Claude Code automatically picks up Spec Kit guidance by pointing to .specify/memory/constitution.md.

Changes:

  • Added ensure_claude_md() helper to generate a root CLAUDE.md for Claude projects (preserving any existing file).
  • Wired Claude-specific CLAUDE.md generation into the init() flow and step tracker.
  • Added an end-to-end CLI test asserting CLAUDE.md is created and contains expected guidance.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/specify_cli/__init__.py Adds ensure_claude_md() and calls it during init() for --ai claude.
tests/test_ai_skills.py Adds a CLI test to verify CLAUDE.md is created during offline init.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

generate CLAUDE.md only when `.specify/memory/constitution.md` exists to avoid misleading guidance, and make the regression test deterministic by patching init scaffolding.

Made-with: Cursor
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mnriem
Copy link
Copy Markdown
Collaborator

mnriem commented Apr 9, 2026

@dhilipkumars Can you see if this still needs to be done?

@mnriem mnriem assigned mnriem and unassigned mnriem Apr 9, 2026
@dhilipkumars
Copy link
Copy Markdown
Contributor

@arun-gupta

Claude code has now merged custom commands with skills as mentioned here

image

and when i initialize speck-kit for claude it automatically creates skills, do see any reason to still support legacy commands?

specify init speckit-test1 --ai claude --script sh

and do this

ls -lart speckit-test1/.claude/skills/*/*.md
  -rw-r--r--@ 1 user  staff  10647 Apr  9 17:05 speckit-test1/.claude/skills/speckit-analyze/SKILL.md
  -rw-r--r--@ 1 user  staff  20093 Apr  9 17:05 speckit-test1/.claude/skills/speckit-checklist/SKILL.md
  -rw-r--r--@ 1 user  staff  14248 Apr  9 17:05 speckit-test1/.claude/skills/speckit-clarify/SKILL.md
  -rw-r--r--@ 1 user  staff   8374 Apr  9 17:05 speckit-test1/.claude/skills/speckit-constitution/SKILL.md
  -rw-r--r--@ 1 user  staff  10688 Apr  9 17:05 speckit-test1/.claude/skills/speckit-implement/SKILL.md
  -rw-r--r--@ 1 user  staff   6241 Apr  9 17:05 speckit-test1/.claude/skills/speckit-plan/SKILL.md
  -rw-r--r--@ 1 user  staff  16399 Apr  9 17:05 speckit-test1/.claude/skills/speckit-specify/SKILL.md
  -rw-r--r--@ 1 user  staff   9202 Apr  9 17:05 speckit-test1/.claude/skills/speckit-tasks/SKILL.md
  -rw-r--r--@ 1 user  staff   4144 Apr  9 17:05 speckit-test1/.claude/skills/speckit-taskstoissues/SKILL.md
  -rw-r--r--@ 1 user  staff   3501 Apr  9 17:05 speckit-test1/.claude/skills/speckit-git-feature/SKILL.md
  -rw-r--r--@ 1 user  staff   2015 Apr  9 17:05 speckit-test1/.claude/skills/speckit-git-validate/SKILL.md
  -rw-r--r--@ 1 user  staff   1627 Apr  9 17:05 speckit-test1/.claude/skills/speckit-git-remote/SKILL.md
  -rw-r--r--@ 1 user  staff   1808 Apr  9 17:05 speckit-test1/.claude/skills/speckit-git-initialize/SKILL.md
  -rw-r--r--@ 1 user  staff   2024 Apr  9 17:05 speckit-test1/.claude/skills/speckit-git-commit/SKILL.md

and skills work the exact same way as legacy slash commands you can invoke them with /, do you want to give the latest spec-kit a try and let us know?

@arun-gupta
Copy link
Copy Markdown
Author

@dhilipkumars, this is not about Claude's commands. It's about generating a minimal CLAUDE.md that points to constitution.md. Otherwise, I have to generate this file for all my projects.

@dhilipkumars
Copy link
Copy Markdown
Contributor

dhilipkumars commented Apr 10, 2026

i see what you mean i would rather recommend them as part of Pre-execution check in specify.md that will work for all the agents instead of Claude.md file , something like this.

  ## Pre-Execution Checks

  **Load project constitution (if present)**:
  - Check if `.specify/memory/constitution.md` exists in the project root.
  - If it exists, read it and extract all active principles and governance rules.
  - Apply them as non-negotiable constraints throughout every subsequent step in this command.
  - If it does not exist, continue with default behaviour — skip silently.
  
  **Check for extension hooks (before specification)**:
- Check if `.specify/extensions.yml` exists in the project root.

may be we should do that for all the commands like plan, tasks and implement

what do you think ? @arun-gupta and @mnriem

@mnriem
Copy link
Copy Markdown
Collaborator

mnriem commented Apr 10, 2026

@dhilipkumars The Claude specific integration could deal with it. Note that the update-agent-context script actually does update those specific files

@arun-gupta
Copy link
Copy Markdown
Author

arun-gupta commented Apr 10, 2026

@dhilipkumars where would this pre-execution checks be placed? In CLAUDE.md? Currently there is nothing generated.

Here is what is working for me https://github.com/arun-gupta/repo-pulse/blob/main/CLAUDE.md

@dhilipkumars
Copy link
Copy Markdown
Contributor

dhilipkumars commented Apr 10, 2026

@dhilipkumars where would this pre-execution checks be placed? In CLAUDE.md? Currently there is nothing generated.

Here is what is working for me https://github.com/arun-gupta/repo-pulse/blob/main/CLAUDE.md

@arun-gupta my suggestions was to bake this indirection in the command/skill directly for eg: here is the specify prompt --> https://github.com/github/spec-kit/blob/main/templates/commands/specify.md

i think @mnriem is leaning towards having this logic in update-agent-context script which also updates Claud.md when Plan phase is triggered for the first time. I wonder if this will still miss constitutional guardrails if we want to enforce during specify phase.

WDYT?

@mnriem
Copy link
Copy Markdown
Collaborator

mnriem commented Apr 10, 2026

What I meant is really 2 fold here. The Claude integration at specify init time can merge/create CLAUDE.md with whatever we think should be in there. Then later on it will be updated by update-agent-context as part of the regular flow

@dhilipkumars
Copy link
Copy Markdown
Contributor

dhilipkumars commented Apr 10, 2026

What I meant is really 2 fold here. The Claude integration at specify init time can merge/create CLAUDE.md with whatever we think should be in there. Then later on it will be updated by update-agent-context as part of the regular flow

gotcha thanks, okay then lets get this PR merged away @arun-gupta please address the co-pilot review comments/resolve conflicts.

@mnriem
Copy link
Copy Markdown
Collaborator

mnriem commented Apr 10, 2026

But as it currently stands it is NOT doing the work in the integration code and that needs to be changed

@arun-gupta
Copy link
Copy Markdown
Author

gotcha thanks, okay then lets get this PR merged away @arun-gupta please address the co-pilot review comments/resolve conflicts.

@dhilipkumars I updated the PR a while back and now have resolved the conversation. Let me know if anything else is required.

@dhilipkumars
Copy link
Copy Markdown
Contributor

@dhilipkumars I updated the PR a while back and now have resolved the conversation. Let me know if anything else is required.

@arun-gupta id start with the following

  • merge conflict needs to be resolved,
  • as @mnriem mentioned this PR resolves init time integration with CLAUDE.md, but it doesn't handle update-agent-context integration yet? can you make required changes and test that out please?

@mnriem
Copy link
Copy Markdown
Collaborator

mnriem commented Apr 10, 2026

It needs to be updated to use src/specify_cli/integrations/claude/__init__.py because we are moving all integration specific code into its own integration so it is more manageable

…1983

# Conflicts:
#	src/specify_cli/__init__.py
#	tests/test_ai_skills.py
@arun-gupta
Copy link
Copy Markdown
Author

Test results after merge resolution

This PR has been rebased/merged against the latest main, which included a significant refactor to an integration-based init system. The original change has been ported to the new architecture — ensure_claude_md now lives on ClaudeIntegration and is invoked from ClaudeIntegration.setup(). The created file is appended to the returned created list and recorded in the integration manifest.

New unit tests

4 new tests in tests/integrations/test_integration_claude.py::TestClaudeMdCreation:

tests/integrations/test_integration_claude.py::TestClaudeMdCreation::test_setup_creates_claude_md_when_constitution_exists PASSED
tests/integrations/test_integration_claude.py::TestClaudeMdCreation::test_setup_skips_claude_md_when_constitution_missing PASSED
tests/integrations/test_integration_claude.py::TestClaudeMdCreation::test_setup_preserves_existing_claude_md PASSED
tests/integrations/test_integration_claude.py::TestClaudeMdCreation::test_init_cli_creates_claude_md PASSED

Coverage:

  • CLAUDE.md is created when .specify/memory/constitution.md exists
  • CLAUDE.md creation is skipped when constitution is missing (gate preserved from original PR)
  • Existing CLAUDE.md is preserved (not overwritten)
  • End-to-end CLI invocation via specify init --here --ai claude creates the file

Full Claude integration suite

All 23 tests pass:

tests/integrations/test_integration_claude.py ..... 23 passed in 0.30s

Full repo test suite

1225 passed, 18 skipped, 1 failed in 13.41s

The single failure (tests/integrations/test_cli.py::TestForceExistingDirectory::test_without_force_errors_on_existing_dir) is pre-existing on upstream/main and unrelated to this PR — the test substring-checks for "already exists" against raw output that now contains it inside a Rich panel with line-wrapping.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for generating a root CLAUDE.md during Claude integration setup so Claude Code has a stable entrypoint that points to the project’s .specify/memory/constitution.md.

Changes:

  • Add ClaudeIntegration.ensure_claude_md() and call it from ClaudeIntegration.setup() to create and manifest-track a minimal root CLAUDE.md when the constitution exists.
  • Add integration tests covering creation, skipping when constitution is missing, and preserving an existing CLAUDE.md.
  • Add a CLI-level integration test to verify specify init --ai claude results in CLAUDE.md being present.
Show a summary per file
File Description
src/specify_cli/integrations/claude/init.py Creates CLAUDE.md during Claude setup (gated on constitution existence) and records it in the integration manifest.
tests/integrations/test_integration_claude.py Adds tests to validate CLAUDE.md creation behavior in both integration setup and CLI init flows.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comments suppressed due to low confidence (1)

src/specify_cli/integrations/claude/init.py:172

  • The generated CLAUDE.md lists core SpecKit commands but omits /speckit.constitution, which is part of the standard workflow (and is shown as a first next-step in init output). Consider adding it to the command list (or otherwise aligning the generated guidance with the supported slash commands).
            "## SpecKit Commands\n"
            "- `/speckit.specify` — generate spec\n"
            "- `/speckit.plan` — generate plan\n"
            "- `/speckit.tasks` — generate task list\n"
            "- `/speckit.implement` — execute plan\n\n"
  • Files reviewed: 2/2 changed files
  • Comments generated: 2

Copy link
Copy Markdown
Collaborator

@mnriem mnriem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address Copilot feedback

@dhilipkumars
Copy link
Copy Markdown
Contributor

It needs to be updated to use src/specify_cli/integrations/claude/__init__.py because we are moving all integration specific code into its own integration so it is more manageable

noted.

- Introduce CONSTITUTION_REL_PATH constant in specify_cli and reuse it
  in ensure_constitution_from_template and ClaudeIntegration.ensure_claude_md
  so the path cannot drift between init scaffolding and integration setup.
- Make ensure_claude_md a classmethod that uses cls.context_file instead
  of hardcoding "CLAUDE.md".
- Expand CLAUDE.md body to list all core speckit workflow commands
  (constitution, specify, clarify, plan, tasks, analyze, checklist,
  implement) so Claude Code sees the full workflow.
- Strengthen tests to assert every section header and every command
  line via shared EXPECTED_CLAUDE_MD_SECTIONS / _COMMANDS constants.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to ensure specify init --ai claude produces a minimal root CLAUDE.md that points Claude Code at the project’s constitution (.specify/memory/constitution.md), and adds regression tests for that behavior.

Changes:

  • Add a shared CONSTITUTION_REL_PATH constant and use it when copying the constitution into .specify/memory/.
  • Implement ClaudeIntegration.ensure_claude_md() and invoke it during Claude integration setup to generate CLAUDE.md when appropriate.
  • Add integration tests asserting CLAUDE.md creation/skipping/preservation and validating expected sections/commands.
Show a summary per file
File Description
src/specify_cli/integrations/claude/__init__.py Adds ensure_claude_md() and appends CLAUDE.md to created files/manifest during Claude setup.
src/specify_cli/__init__.py Introduces CONSTITUTION_REL_PATH and reuses it in ensure_constitution_from_template().
tests/integrations/test_integration_claude.py Adds coverage for CLAUDE.md generation behavior in both integration setup and CLI init.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 3/3 changed files
  • Comments generated: 2

@mnriem mnriem self-requested a review April 10, 2026 22:41
Copy link
Copy Markdown
Collaborator

@mnriem mnriem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address Copilot feedback. If not applicable, please explain why. Hopefully this is the last review needed. Thanks for working on this!

The previous placement called ensure_claude_md() from
ClaudeIntegration.setup(), which runs BEFORE
ensure_constitution_from_template() in the init() flow. Since the
creation is gated on the constitution file existing, CLAUDE.md was
silently skipped on a fresh `specify init --ai claude` — the exact
scenario this PR is meant to fix.

The previous tests masked this bug by pre-creating the constitution
file before invoking setup() or the CLI, so they never exercised the
real ordering.

Fix:
- Add a generic `ensure_context_file(project_root, manifest)` hook on
  IntegrationBase (default no-op) that runs after the constitution is
  in place. Integrations needing a root context file (e.g. CLAUDE.md)
  override it.
- Move the CLAUDE.md creation from ClaudeIntegration.setup() into
  ClaudeIntegration.ensure_context_file(), which also records the file
  in the integration manifest.
- Call resolved_integration.ensure_context_file(...) from init()
  immediately after ensure_constitution_from_template(...), and
  re-save the manifest if a file was created.

Tests:
- Rewrite the CLI end-to-end test to start from a truly empty project
  (no pre-created constitution) so it fails if the ordering regresses.
  It now asserts that BOTH the constitution and CLAUDE.md exist.
- Add a test proving setup() alone does NOT create CLAUDE.md.
- Update the three unit tests to call ensure_context_file directly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a post-constitution initialization hook so the Claude integration can generate a minimal root CLAUDE.md that points Claude Code at the project’s authoritative constitution file (.specify/memory/constitution.md), addressing the missing-file behavior in specify init --ai claude.

Changes:

  • Introduces an IntegrationBase.ensure_context_file() hook (no-op by default) intended to run after constitution setup during specify init.
  • Implements ClaudeIntegration.ensure_context_file() to create CLAUDE.md when the constitution exists and no CLAUDE.md is present.
  • Adds integration tests verifying creation/skip/preservation behaviors and an init-flow ordering check.
Show a summary per file
File Description
src/specify_cli/__init__.py Defines a shared CONSTITUTION_REL_PATH and invokes the new post-constitution integration hook during init().
src/specify_cli/integrations/base.py Adds the new ensure_context_file() extension point to the integration base class.
src/specify_cli/integrations/claude/__init__.py Implements Claude-specific creation of root CLAUDE.md and records it in the integration manifest.
tests/integrations/test_integration_claude.py Adds unit + init-flow tests covering CLAUDE.md creation logic and ordering.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comments suppressed due to low confidence (1)

src/specify_cli/integrations/claude/init.py:194

  • For consistency with other manifest-tracked file writes, prefer using IntegrationBase.write_file_and_record() to write+record CLAUDE.md (it also normalizes newlines). Using write_text() + record_file_in_manifest() bypasses that standard path.
        )
        context_file.write_text(content, encoding="utf-8")
        self.record_file_in_manifest(context_file, project_root, manifest)
        return context_file
  • Files reviewed: 4/4 changed files
  • Comments generated: 2

mnriem and others added 2 commits April 10, 2026 18:06
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Ensures specify init --ai claude generates a minimal root CLAUDE.md that points Claude Code at the authoritative constitution file, fixing the missing-context-file gap in the Claude init flow.

Changes:

  • Add a shared CONSTITUTION_REL_PATH constant and use it for constitution scaffolding.
  • Introduce an IntegrationBase.ensure_context_file() post-constitution hook and invoke it during init.
  • Implement the hook for the Claude integration and add integration tests asserting the correct behavior.
Show a summary per file
File Description
tests/integrations/test_integration_claude.py Adds unit + end-to-end coverage for creating/preserving CLAUDE.md based on constitution presence.
src/specify_cli/integrations/claude/init.py Implements ensure_context_file() to generate minimal CLAUDE.md when constitution exists.
src/specify_cli/integrations/base.py Adds the ensure_context_file() hook to the integration base API (default no-op).
src/specify_cli/init.py Centralizes constitution path via CONSTITUTION_REL_PATH and calls the new hook after constitution setup in init().

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

@mnriem mnriem self-requested a review April 10, 2026 23:12
Copy link
Copy Markdown
Collaborator

@mnriem mnriem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address Copilot feedback, if not applicable please explain why

…ests

Addresses two review comments:

- ensure_context_file now uses the base class's write_file_and_record()
  helper instead of Path.write_text + a separate record_file_in_manifest
  call. This matches the pattern used everywhere else in integrations,
  normalizes \r\n -> \n to avoid platform newline translation, and keeps
  the write+manifest update consistent.
- Tests now import and use CONSTITUTION_REL_PATH instead of hardcoding
  ".specify/memory/constitution.md", so the path stays in sync with the
  production constant.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: specify init --ai claude does not generate CLAUDE.md

4 participants